import React from 'react'
// 导入鼠标图片
// import img from './assets/mouse.jpg'


// 组件复用
class App extends React.Component {
    constructor() {
        super()
        this.state = {
            name: 'Brave',
            age: 18,
            x: 0,
            y: 0
        }
    }
    handel = (e) => {
        this.setState({
            x: e.clientX,
            y: e.clientY
        })

    }
    componentDidMount() {
        window.addEventListener('mousemove', this.handel)
    }
    render() {
        return this.props.render(this.state)
    }
}

class Mouse extends React.Component {
    render() {
        return (
            <App render={
                mouse => {
                    return (
                        <h2> 鼠标位置---X：{mouse.x}，Y：{mouse.y}</h2>
                    )
                }
            }></App>
        )
    }
}


// 组件复用---添加图片
class Img extends React.Component {
    render() {
        return (
            <div>
                <App render={mouse => {
                    return (
                        <h2>鼠标的位置---X：{mouse.x}，Y：{mouse.y}</h2>
                    )
                }}>

                </App>
                <App render={mouse => {
                    return (
                        <div style={{
                            position: 'absolute',
                            top: mouse.y - 50,
                            left: mouse.x - 50,
                            width: 100,
                            height: 100,
                            borderRadius: 50,
                            backgroundColor: 'pink'
                        }}></div>
                    )
                }}></App>
            </div>
        )
    }
}


// 组件复用 Children   ---类似于插槽
class Children extends React.Component {
    constructor() {
        super()
        this.state = {
            x: 0,
            y: 0
        }
    }
    handel = (e) => {
        this.setState({
            x: e.clientX,
            y: e.clientY
        })
    }
    componentDidMount() {
        window.addEventListener('mousemove', this.handel)
    }

    render() {
        return this.props.children(this.state)
    }
}

class Fu extends React.Component {
    render() {
        return (
            <div>
                <Children>
                    {
                        (mouse) => (
                            <p>鼠标位置: X: { mouse.x}， Y: {mouse.y}</p>
                        )
                    }
                </Children>
                <Children>
                    {
                        (mouse) => (
                            <div style={{
                                position: 'absolute',
                                top: mouse.y - 50,
                                left: mouse.x - 50,
                                width: 100,
                                height: 100,
                                borderRadius: 50,
                                backgroundColor: 'pink'
                            }}></div>
                        )
                    }
                </Children>
            </div>
        )
    }
}






// HOC高阶组件
// 1. 创建一个函数名，函数名约定为With开头
// 2. 指定参数，参数名开头以大写
// 3.在函数名内创建一个类组件，并返回
function WithMouse(WrapperComponent) {
    class Hoc extends React.Component {
        state = {
            x: 0,
            y: 0
        }
        handel = (e) => {
            this.setState({
                x: e.clientX,
                y: e.clientY
            })
        }

        componentDidMount() {
            window.addEventListener('mousemove', this.handel)
        }
        componentWillMount() {
            window.removeEventListener('mousemove', this.handel)
        }

        //    4.在该组件中渲染WrapperComponent并将状态通过props传递进去
        render() {
            // 在该组件中，渲染参数组件，同时将状态通过prop传递给参数组件
            return <WrapperComponent {...this.state}{...this.props}></WrapperComponent>
        }
    }

    // 设置 displayName
    Hoc.displayName = `WithSubscription(${getDisplayName(WrapperComponent)})`;
    function getDisplayName(WrappedComponent) {
        return WrappedComponent.displayName || WrappedComponent.name || 'Component';
    }

    return Hoc

}
// 5. 调用该组件，传入要增强的组件，通过返回值拿到增强后的组件，并将其渲染到页面中
const position = props => (
    <p>鼠标的位置---X：{props.x}，Y：{props.y}</p>
)
// 6. 获取增强后的组件
const MousePosition = WithMouse(position)

class Test extends React.Component {
    render() {
        return (
            <div>
                <MousePosition></MousePosition>
            </div>
        )
    }
}





// 组件性能优化
class Hello extends React.Component {
    componentDidMount() {
      // timerId存储到this中，而不是state中
      this.timerId = setInterval(() => {}, 2000)
    }
  
    componentWillUnmount() {
      clearInterval(this.timerId)
    }
    
    render() {
        return (
            <div>
                666
          </div>
      )
    }
}
  
class Word extends React.Component{
    state = {
        age: 1,
        num: 1
    }
    handleClick = () => {
        this.setState({
            age: this.state.age + 1,
            num:Math.floor(Math.random()*5)
        })
    }
    shouldComponentUpdate(nextProps, nextState) {
        // 获取最新的 props 值
        console.log(nextProps)
        // 获取最新的 state 状态
        console.log(nextState)
    
        // 根据返回值，决定是否重新渲染组件
        // return true --- 重新渲染组件
        // return false --- 不重新渲染组件
        return this.state.num !== nextState.num
    }
    render() {
        return (
            <div>
            <p>{this.state.age}</p>
            <p>{this.state.num}</p>
            <Son num={this.state.num}></Son>
            <button onClick={this.handleClick}>点击 + 1</button>
          </div>
        )
    }
}

class Son extends React.Component {
    shouldComponentUpdate (nextProps, nextState) {
      // 当最新的 props 值 和 上次的 props 值一致时，阻止更新
      if (this.props.num === nextProps.num) {
        return false
      }
  
      return true
    }
  
    render() {
      return (
        <div>{this.props.num}</div>
      )
    }
  }




//   纯组件
class Chun extends React.PureComponent{
    state = { number: 0 }
    render() {
        return (
            <div>
                { this.state.number }
            我是纯组件
            </div>
        )
    }
}



// 虚拟Dom
// 生成随机数
class Dom extends React.PureComponent {
    state = {
      number: 0
    }
  
    handleClick = () => {
      this.setState(() => {
        return {
          number: Math.floor(Math.random() * 2)
        }
      })
    }
  
    // render方法调用并不意味着浏览器中的重新渲染！！！
    // render方法调用仅仅说明要进行diff
    render() {
      const el = (
        <div>
          <h1>随机数：</h1>
          <p>{this.state.number}</p>
          <button onClick={this.handleClick}>重新生成</button>
        </div>
      )
      console.log(el)
  
      return el
    }
  }








export default Dom